#ifndef SERVER
#define SERVER

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "hot.hpp"
#include "httplib.h"
#include <thread>

extern bucai::DataManager dm;
namespace bucai
{
    class server{
    private:
        int _server_port;
        std::string _server_ip;
        std::string _download_prefix;
        static httplib::Server _ser;
    public:
        static void Upload(const httplib::Request &req, httplib::Response& rsp){ //上传文件
            const auto exist = req.has_file("file");
            if(exist == false){
                std::cout<< "file not exist" << std::endl;
                rsp.status = 404;
                return;
            }
            //获取文件名字、正文内容
            const auto& file = req.get_file_value("file");
            std::string pack_dir = bucai::Config::getConfig()->GetPackDir();
            std::string realpath = pack_dir + bucai::fileUtil(file.filename).FileName();

            bucai::fileUtil fu(realpath);
            fu.SetContent(file.content);

            //把新增的文件加入内容管理中
            bucai::DataInfo di;
            di.NewDataInfo(realpath);

            std::cout << "server:> insert di.url is :>" << di.url << std::endl;
            dm.Insert(di.url, di);

            rsp.set_redirect("/");//重定向到根目录
            //bucai::server::_ser.Get("/",List);
        }

        
        static std::string TimetoStr(time_t t) {
				std::string tmp = std::ctime(&t);
				return tmp;
		}
        static void List(const httplib::Request &req, httplib::Response &rsp){//展示所有文件
            std::vector<bucai::DataInfo> vec;
            dm.GetAll(&vec);//获取出所有的文件信息

            //2. 根据所有备份信息，组织html文件数据
            std::stringstream ss;
            ss << "<html><head><meta charset=\"UTF-8\"><title>Download</title></head>";
            ss << "<body><h1>Download</h1><table>";
            ss << R"(<form action="http://47.107.49.227:9090/upload" method="post" enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="上传"></form>)";
            for(auto e : vec){
                ss << "<tr>";
                std::string filename = bucai::fileUtil(e.realpath).FileName();
                ss << "<td><a href=\"" << e.url << "\">" << filename << "</a></td>";
                ss << "<td align=\"right\">" << TimetoStr(e.atime) << "</td>";
                ss << "<td align= \"right\">" << e.fsize / 1024 << "k" << "</td>";
                ss << "</tr>";
            }
            ss << "</table></body></html>";
            //返回所有的文件内容
            rsp.body = ss.str();
            rsp.set_header("Content-Type", "text/html");
            rsp.status = 200;
            
        }
        static std::string GetETag(const bucai::DataInfo &info) {
				// etg :  filename-fsize-mtime
				bucai::fileUtil fu(info.realpath);
				std::string etag = fu.FileName();
				etag += "-";
				etag += std::to_string(info.fsize);
				etag += "-";
				etag += std::to_string(info.mtime);
				return etag;
		}
        
        static void Download(const httplib::Request &req, httplib::Response& rsp){
            bucai::DataInfo di;
            //std::cout<< "req.path:> " << req.path << std::endl;
            bool isTrue = dm.GetOneByURL(req.path, &di);
            if(isTrue == false){
                rsp.status = 500;
                std::cout<< "server :> isTrue == false;  req.path:> " << req.path << std::endl << std::endl;
                return;
            }
            // else{
            //     std::cout<< "server :> GetOneByURL is true" << std::endl;

            // }
            //判断是否压缩
            if(di.pack_flag == true){ //已压缩的进行解压
                bucai::fileUtil fu(di.packpath);
                bool Unzip = fu.UnCompress(di.realpath);//解压

                if(Unzip == true){
                    std::cout<< "server :> fu.UnCompress(di.realpath) true" << std::endl;
                }
                
                fu.Remove();//删除back_dir中的压缩文件
                di.pack_flag = false;
				dm.Update(di.url, di);
            }
            bucai::fileUtil fu(di.realpath);
            std::string body;
            fu.GetContent(&body);
            rsp.body = body;
            rsp.set_header("Accept-Ranges", "bytes");
            rsp.set_header("ETag", GetETag(di));
            rsp.set_header("Content-Type", "application/octet-stream");
            rsp.status = 200;
        }

    public:
        server(){
            bucai::Config* con = bucai::Config::getConfig();
            _server_ip = con->GetServerIp();
            _server_port = con->GetServerPort();
            _download_prefix = con->GetURLPrefix();
        }
        bool RunModule(){


            bucai::server::_ser.Post("/upload", Upload);
            bucai::server::_ser.Get("/list",List);
            bucai::server::_ser.Get("/",List);
            std::string down = _download_prefix + "(.*)";// .*是正则表达式

            std::cout << down << std::endl;

            //_ser.Get(R"(./download/(.*))",Download);
            bucai::server::_ser.Get(down,Download);
            bucai::server::_ser.listen(_server_ip.c_str(), _server_port);
            return true;
        }
    };
    httplib::Server bucai::server::_ser;

    
} // namespace bucai

#endif

